﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.IO;

namespace SkypeTranslator.Utilities
{
	internal static class WinApi
	{
		internal const int DBT_DEVTYP_HANDLE = 6;
		internal const int BROADCAST_QUERY_DENY = 0x424D5144;
		internal const int WM_DEVICECHANGE = 0x0219;
		internal const int DBT_DEVICEARRIVAL = 0x8000; // system detected a new device
		internal const int DBT_DEVICEQUERYREMOVE = 0x8001;   // Preparing to remove (any program can disable the removal)
		internal const int DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed 
		internal const int DBT_DEVTYP_VOLUME = 0x00000002; // drive type is logical volume
		internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
		internal const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;

		// Structure with information for RegisterDeviceNotification.
		[StructLayout(LayoutKind.Sequential)]
		public struct DEV_BROADCAST_HANDLE
		{
			public int dbch_size;
			public int dbch_devicetype;
			public int dbch_reserved;
			public IntPtr dbch_handle;
			public IntPtr dbch_hdevnotify;
			public Guid dbch_eventguid;
			public long dbch_nameoffset;
			//public byte[] dbch_data[1]; // = new byte[1];
			public byte dbch_data;
			public byte dbch_data1;
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct STORAGE_DEVICE_NUMBER
		{
			public int DeviceType;
			public int DeviceNumber;
			public int PartitionNumber;
		}

		[StructLayout(LayoutKind.Explicit, Size = 20)]
		public struct OVERLAPPED
		{
			[FieldOffset(0)]
			public uint Internal;
			[FieldOffset(4)]
			public uint InternalHigh;
			[FieldOffset(8)]
			public uint Offset;
			[FieldOffset(12)]
			public uint OffsetHigh;
			[FieldOffset(8)]
			public IntPtr Pointer;
			[FieldOffset(16)]
			public IntPtr hEvent;
		}

		[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern SafeFileHandle CreateFile(string lpFileName, [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
			 [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
			 IntPtr lpSecurityAttributes,
			 [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
			 [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
			 IntPtr hTemplateFile);

		[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		internal static extern bool DeviceIoControl(SafeFileHandle hDevice,
				uint dwIoControlCode,
				IntPtr InBuffer,
				int nInBufferSize,
				ref long OutBuffer,
				int nOutBufferSize,
				ref int pBytesReturned,
				[In] ref OVERLAPPED lpOverlapped);

		[return: MarshalAs(UnmanagedType.Bool)]
		[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		internal static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] int dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize,
			[Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);

		[DllImport(@"hid.dll", CharSet = CharSet.Auto, SetLastError = true)]
		internal static extern void HidD_GetHidGuid(out Guid gHid);

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, uint Flags);

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		public static extern uint UnregisterDeviceNotification(IntPtr hHandle);

		[StructLayout(LayoutKind.Sequential)]
		public struct SHFILEINFO
		{
			public IntPtr hIcon;
			public IntPtr iIcon;
			public uint dwAttributes;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
			public string szDisplayName;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
			public string szTypeName;
		};

		public const uint SHGFI_ICON = 0x100;
		public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
		public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

		/// <summary>
		/// <example>
		/// fName = openFileDialog1.FileName;
		///Use this to get the small Icon
		///hImgSmall = Win32.SHGetFileInfo(fName, 0, ref shinfo,(uint)Marshal.SizeOf(shinfo),Win32.SHGFI_ICON |Win32.SHGFI_SMALLICON);
		///Use this to get the large Icon
		///hImgLarge = SHGetFileInfo(fName, 0, 
		///	ref shinfo, (uint)Marshal.SizeOf(shinfo), 
		///	Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
		///The icon is returned in the hIcon member of the shinfo struct
		///System.Drawing.Icon myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
		/// </example>
		/// </summary>
		/// <param name="pszPath"></param>
		/// <param name="dwFileAttributes"></param>
		/// <param name="psfi"></param>
		/// <param name="cbSizeFileInfo"></param>
		/// <param name="uFlags"></param>
		/// <returns></returns>
		[DllImport("shell32.dll")]
		internal static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

		[DllImport("shell32.dll")]
		[return:MarshalAs( UnmanagedType.Bool)]
		internal static extern bool IsUserAnAdmin();

	}
}
